﻿using Microsoft.EntityFrameworkCore;

namespace EFCore;

class Program
{
    static async Task Main(string[] args)
    {
        using (var context = new AppDbContext())
        {
            // EF Core 的所有数据库操作都通过 DbContext 实例进行

            // 执行简单练习
            // await RunEasyExerxises(context);

            // 执行中等练习
            await RunMediumExercises(context);

            //困难
            // await RunHardExercises(context);
        }
    }

    //简单
    static async Task RunEasyExerxises(AppDbContext context)
    {
        //新增用户
        Console.WriteLine("新增用户");
        var newUser = new User
        {
            Name = "Jay",
            Email = $"{Guid.NewGuid()}@gmail.com",
            RegistrationDate = DateTime.Now
        };
        // 将新用户添加到 DbSet 中，标记为 Added
        context.Users.Add(newUser);
        //更改保存到数据库
        await context.SaveChangesAsync();

        // 查找用户
        var selectUser = await context.Users.FindAsync(newUser.Id);
        if (selectUser != null)
        {
            Console.WriteLine($"找到用户{newUser.Id} 用户名 {selectUser.Name} 邮箱为 Email:{selectUser.Email}");
        }
        else
        {
            Console.WriteLine($"没有找到相关的用户{newUser.Id}");
        }

        //列出所有博客文章的标题
        // Select 进行投影，ToListAsync 立即执行查询并返回 List<string>
        var postTitle = await context.Posts.Select(p => p.Title).ToListAsync();
        Console.WriteLine($"所有文章");
        foreach (var titles in postTitle)
        {
            Console.WriteLine($"{titles}");
        }

        // 简单练习 4: 更新 ID 为 X 的用户的邮箱地址。
        var userUpdate = await context.Users.FirstOrDefaultAsync(u => u.Id == newUser.Id);

        if (userUpdate != null)
        {
            userUpdate.Email = "alice.updae@gmail.com";
            await context.SaveChangesAsync();
            Console.WriteLine($"用户ID {userUpdate} 邮箱已更新");
        }
        else
        {
            Console.WriteLine($"没有找到相关的用户{userUpdate}进行更新");
        }

        // 简单练习 5: 删除 ID 为 Y 的用户

        var deleteUser = await context.Users.FirstOrDefaultAsync(u => u.Id == newUser.Id);

        if (deleteUser != null)
        {
            context.Users.Remove(deleteUser);
            await context.SaveChangesAsync();

            var deletedUserCheck = await context.Users.FindAsync(newUser.Id);
            Console.WriteLine($"查找 Id {newUser.Id} 的用户结果: {(deletedUserCheck == null ? "未找到" : "找到 (删除失败)")}");
        }
        else
        {
            Console.WriteLine($"未找到 Id 为 {newUser.Id} 的用户进行删除.");
        }
    }

    //中等
    static async Task RunMediumExercises(AppDbContext context)
    {
        Console.WriteLine("\n--- 中等练习 ---"); // 加上标题更清晰

        // 中等练习 1: 为指定用户（通过 ID）添加一篇新博客文章。
        // Console.WriteLine("练习 1: 为用户 (Id=2) 添加新文章..."); // 加上练习说明
        /*int userId = 2; // Bob 的 ID

        // 查找用户是否存在 (可选但推荐，确保外键有效)
        var existingAuthor = await context.Users.FindAsync(userId);
        if (existingAuthor == null)
        {
            Console.WriteLine($"未找到 Id 为 {userId} 的用户，无法添加文章。");
            return; // 退出方法或处理错误
        }

        var newPost = new Post
        {
            Title = "学习EFCore",
            Content = "一个非常重要的知识点EFCore",
            PublishedDate = DateTime.Now,
            AuthorId = userId
        };

        context.Posts.Add(newPost); // 或者使用 context.Add(newPost);
        Console.WriteLine("准备保存新文章...");

        // 更改保存到数据库
        await context.SaveChangesAsync(); // <-- 在这里，newPost.Id 会被数据库生成的 ID 更新

        Console.WriteLine($"新文章 '{newPost.Title}' (Id: {newPost.Id}) 已成功为用户 '{existingAuthor.Name}' 添加.");

        // 验证添加：直接使用 newPost 对象，它的 Id 已经被更新了
        // 不需要再次查询数据库来验证刚刚添加的对象，除非你有其他需要验证的属性
        Console.WriteLine($"验证信息: 新文章 Id: {newPost.Id}, Title: {newPost.Title}, Content: {newPost.Content}");*/

        // 中等练习 2: 列出所有文章及其作者的姓名。
        // 使用 Include 加载关联的 Author 实体
        var authorAsync = await context.Posts.Include(p => p.Author).ToListAsync();
        Console.WriteLine("所有文章及其作者的姓名");
        foreach (var authorOrUserName in authorAsync)
        {
            Console.WriteLine($"文章 {authorOrUserName.Title} 作者 {authorOrUserName.Author.Name}");
        }

        // 中等练习 3: 查找并列出所有针对特定文章（通过 ID）的评论及其评论者姓名。
        Console.WriteLine("\n练习 3: 列出文章 (Id=1) 的评论及其评论者姓名...");
        int postIdToFindComments = 2; // 查找文章 '我的第一篇博客' (Id 1) 的评论
        // 使用 Where 过滤评论，然后 Include 加载关联的 Author 实体
        var comments = await context.Comments
            .Where(c => c.PostId == postIdToFindComments)
            .Include(c => c.Author) // 加载评论的作者
            .ToListAsync();

        Console.WriteLine($"文章 Id {postIdToFindComments} 的评论:");

        if (comments.Any())
        {
            foreach (var comment in comments)
            {
                Console.WriteLine($"- '{comment.Text}' (评论者: {comment.Author.Name})");
            }
        }
        else
        {
            Console.WriteLine("没有找到评论.");
        }

        // 中等练习 4: 计算 ID 为 Z 的用户总共发表了多少篇文章。
        int postIdToFindPosts = 2;
        var countAsync = await context.Posts.CountAsync(p => p.AuthorId == postIdToFindPosts);// 使用 CountAsync 和过滤条件

        var findAsync = await context.Users.FindAsync(postIdToFindPosts);
        if(findAsync != null)
        {
            Console.WriteLine($"用户 '{findAsync.Name}' (Id: {postIdToFindPosts}) 共发表了 {countAsync} 篇文章.");
        }
        else
        {
            Console.WriteLine($"未找到 Id 为 {postIdToFindPosts} 的用户.");
        }
    }

    //困难
    static async Task RunHardExercises(AppDbContext context)
    {
        // 查找至少发表了 N 篇文章的所有用户及其文章数量
        int minPosts = 2;

        var listAsync = await context.Users
            // GroupBy 将用户分组，但这里我们想基于用户的文章来分组，然后获取用户本身和文章数量
            // 更直接的方式是查询 Posts，按 AuthorId 分组，计算每组数量，然后 Join 回 Users 表获取用户信息
            // 或者：直接在 Users 表上执行 GroupBy，然后计算每组 (每个用户) 的 Posts 导航属性的数量
            .Select(user => new
            {
                User = user,
                PostCount = user.Posts.Count // 计算每个用户的文章数量
            }).Where(userWithCount => userWithCount.PostCount >= minPosts) // 过滤：只保留文章数量 >= minPosts 的用户
            .ToListAsync(); // 立即执行查询
        Console.WriteLine($"文章数量>={minPosts}的用户");
        if (listAsync.Any())
        {
            foreach (var x in listAsync)
            {
                Console.WriteLine($"用户 {x.User.Name} 文章数量{x.PostCount}");
            }
        }
        else
        {
            Console.WriteLine($"没有找到文章数量大于{minPosts}的用户");
        }
    }
}